
figures =
{
 {
    { { 1, 0, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 1, 0, 0, 0 } }

  , { { 1, 1, 1, 1 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }
 }
 ,
 {
    { { 1, 0, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 0, 0, 1, 0 }
    , { 1, 1, 1, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 1, 0, 0 }
    , { 0, 1, 0, 0 }
    , { 0, 1, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 1, 1, 0 }
    , { 1, 0, 0, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }
}
,
{
    { { 0, 1, 0, 0 }
    , { 0, 1, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 1, 1, 0 }
    , { 0, 0, 1, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 1, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 0, 0, 0 }
    , { 1, 1, 1, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }
}
,
{
    { { 1, 1, 1, 0 }
    , { 0, 1, 0, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 0, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 0, 1, 0, 0 }
    , { 1, 1, 1, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 0, 1, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 1, 0, 0 }
    , { 0, 0, 0, 0 } }
}
,
{
    { { 1, 1, 0, 0 }
    , { 0, 1, 1, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 0, 1, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 1, 0, 0, 0 }
    , { 0, 0, 0, 0 } }
}
,
{
    { { 0, 1, 1, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }

  , { { 1, 0, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 1, 0, 0 }
    , { 0, 0, 0, 0 } }
 }
,
{
    { { 1, 1, 0, 0 }
    , { 1, 1, 0, 0 }
    , { 0, 0, 0, 0 }
    , { 0, 0, 0, 0 } }
}

}

field = {}
moveDownTimeCurrent = 0;
moveDownTimeNeeded = 1000;
inputUpdateTimeCurrent = 0;
inputUpdateTimeNeeded = 200;
currentFigureRotation = 1;
currentFigureType = 2;
currentFigure = figures[currentFigureType][currentFigureRotation];
currentX = 5;
currentY = 15;
moveDown = false;
moveLeft = false;
moveRight = false;
moveRotate = false;

function main()
    for i=0,10 do
        Test1.SetPixel(i, 0, true);
    end
    for i=1,15 do
        Test1.SetPixel(0, i, true);
        Test1.SetPixel(10, i, true);
    end

    for i=1,15 do
        field[i] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    end
    InputSystem.SubscribeActionKey( "left", 203, 1.0 )
    InputSystem.SubscribeActionKey( "right", 205, 1.0 )
    InputSystem.SubscribeActionKey( "rotate", 200, 1.0 )
    InputSystem.SubscribeActionKey( "down", 208, 1.0 )
    onTick();
end

function updateField()
    for i=1,15 do
        for j=1,9 do
            Test1.SetPixel(j, i, field[i][j] == 1);
        end
    end
end

function fieldSet( x, y, figure, set )
    for j=1,#figure do
        for i=1, #(figure[j]) do
            if figure[j][i] == 1 then
                field[y-j+1][x+i-1] = set
            end
        end
    end
end

function checkCollision( x, y, figure )
    for j=1, #figure do
        for i=1, #(figure[j]) do
            if figure[j][i] == 1 then
                local fx = x+i-1;
                local fy = y-j+1;
                if  fx < 1 or fx > 9 or fy < 1 or field[fy][fx] == 1 then
                    return true;
                end;
            end
        end
    end
    return false;
end

function updateLines()
    local lines = 0;
    for j=1, 15 do
        local s = 0;
        for i=1, 9 do
            s = s + field[j-lines][i];
        end
        if s == 9 then
            table.remove(field, j-lines);
            table.insert(field, {0, 0, 0, 0, 0, 0, 0, 0, 0});
            lines = lines + 1;
        end
    end
end

function nextFigure()
    currentFigureType = math.random(1, #figures);
    currentFigureRotation = 1;
    currentFigure = figures[currentFigureType][currentFigureRotation];
    currentX = 5;
    currentY = 15;
end

function onTick()
    fieldSet(currentX, currentY, currentFigure, 0);
    if moveDown == true then
        if checkCollision(currentX, currentY - 1, currentFigure) == true then
            fieldSet(currentX, currentY, currentFigure, 1);
            updateLines();
            nextFigure();
        else
            currentY = currentY - 1;
        end
        moveDown = false;
    elseif moveRotate == true then
        local nextFigureRotation = (currentFigureRotation) % #(figures[currentFigureType]) + 1;
        if checkCollision(currentX, currentY, figures[currentFigureType][nextFigureRotation]) == false then
            currentFigureRotation = nextFigureRotation;
            currentFigure = figures[currentFigureType][currentFigureRotation];
        end
        Test1.PlayBeep(currentX, currentY, 0);
        moveRotate = false;
    elseif moveLeft == true then
        if checkCollision(currentX-1, currentY, currentFigure) == false then
            currentX = currentX - 1;
        end
        Test1.PlayBeep(currentX, currentY, 0);
        moveLeft = false;
    elseif moveRight == true then
        if checkCollision(currentX+1, currentY, currentFigure) == false then
            currentX = currentX + 1;
        end
        Test1.PlayBeep(currentX, currentY, 0);
        moveRight = false;
    end

    fieldSet(currentX, currentY, currentFigure, 1);
    updateField();
end

function Update( dt )
    moveDownTimeCurrent = moveDownTimeCurrent + dt;
    inputUpdateTimeCurrent = inputUpdateTimeCurrent + dt;

    moveLeft = false;
    moveRight = false;
    moveDown = false;
    moveRotate = false;

    local needTick = false;

    if InputSystem.GetActionWasPressed("left") > 0 then
        moveLeft = true;
        needTick = true;
        inputUpdateTimeCurrent = 0;
    elseif InputSystem.GetActionWasPressed("right") > 0 then
        moveRight = true;
        needTick = true;
        inputUpdateTimeCurrent = 0;
    elseif InputSystem.GetActionWasPressed("rotate") > 0 then
        moveRotate = true;
        needTick = true;
        inputUpdateTimeCurrent = 0;
    elseif InputSystem.GetActionWasPressed("down") > 0 then
        moveDown = true;
        needTick = true;
        moveDownTimeCurrent = 0;
        inputUpdateTimeCurrent = 0;
    end

    if inputUpdateTimeCurrent >= inputUpdateTimeNeeded then
        moveLeft = InputSystem.GetActionIsPressed("left");
        moveRight = InputSystem.GetActionIsPressed("right");
        moveDown = InputSystem.GetActionIsPressed("down");
        moveRotate = InputSystem.GetActionIsPressed("rotate");
        inputUpdateTimeCurrent = 0;
        needTick = true;
    end

    if (moveDown == false) and (moveDownTimeCurrent >= moveDownTimeNeeded) then
        moveDown = true;
        needTick = true;
        moveDownTimeCurrent = 0;
    end

    if needTick == true then
        onTick();
    end
end
